package com.rock.niotest;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;

public class NioEchoServer {

    private Selector selector = null;
    static final int PORT = 8888;

    private Charset charse = Charset.forName("GBK");

    public void init() throws IOException {
//        selector = Selector.open();
//
//        ServerSocketChannel server = ServerSocketChannel.open();
//        InetSocketAddress serverAddress = new InetSocketAddress("127.0.0.1", PORT);
//        server.bind(serverAddress);
//        server.configureBlocking(false);
//        server.register(selector, SelectionKey.OP_ACCEPT);
//        int readyNum = selector.select();
//        int n = 0;
//        while (readyNum > 0 && n <= 10) {
//            System.out.println("select, ready num: "+readyNum);
//             
//            Set<SelectionKey> keys = selector.selectedKeys();
//            
//            for (SelectionKey selectionKey : keys) {
//                processSelectionKey(server, selectionKey);
//            }
//            keys.clear();
//            readyNum = selector.select();
//            n++;
//        }

        
        
        Selector selector = null;
        ServerSocketChannel server = null;
         
            selector = Selector.open(); 
            server = ServerSocketChannel.open(); 
            server.socket().bind(new InetSocketAddress(8888)); 
            server.configureBlocking(false); 
            server.register(selector, SelectionKey.OP_ACCEPT); 
            while (true) {
                selector.select();
                System.out.println("select......");
                for (Iterator<SelectionKey> i = selector.selectedKeys().iterator(); i.hasNext();) { 
                    SelectionKey key = i.next(); 
                    i.remove(); 
                    if (key.isConnectable()) { 
                        ((SocketChannel)key.channel()).finishConnect(); 
                    } 
                    if (key.isAcceptable()) { 
                        // accept connection 
                        SocketChannel client = server.accept(); 
                        client.configureBlocking(false); 
                        client.socket().setTcpNoDelay(true); 
                        client.register(selector, SelectionKey.OP_READ);
                    } 
                    if (key.isReadable()) { 
                        // ...read messages...
                    } 
                }
            }           
               
        
    }

    private void processSelectionKey(ServerSocketChannel server, SelectionKey selectionKey)
            throws IOException, ClosedChannelException {
        if (selectionKey.isConnectable()) { 
            ((SocketChannel)selectionKey.channel()).finishConnect(); 
        } 
        else if (selectionKey.isAcceptable()) {
            SocketChannel client = server.accept();
            client.configureBlocking(false);
            client.register(selector, SelectionKey.OP_READ);
            System.out.println("connection accepted ");
        }

        else if (selectionKey.isReadable()) {
            System.out.println("connection read data ");
            SocketChannel sc = (SocketChannel) selectionKey.channel();
            ByteBuffer buff = ByteBuffer.allocate(1024);
            String content = "";
            try {
                while (sc.read(buff) > 0) {
                    buff.flip();
                    content += charse.decode(buff);
                }
                System.out.println("读取的数据：" + content);

               

                sc.write(charse.encode(content));
            } catch (IOException io) {
                selectionKey.cancel();
                if (selectionKey.channel() != null) {
                    selectionKey.channel().close();
                }
            }

 
        }
        else{
            System.out.println("connection other opp... ");
        }
    }

    public static void main(String[] args) throws IOException {
        new NioEchoServer().init();
    }
    
    
    public static void main2(String args[]) throws Exception
    { 
        Selector selector = Selector.open();
        
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        InetSocketAddress address = new InetSocketAddress(8888);
        serverSocketChannel.socket().bind(address);
        
        
         serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        
        
        while (true){
            int selectedNum = selector.select();
            System.out.println("Selected Number is :"+selectedNum);
            Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
            
            while(iter.hasNext()){
                SelectionKey selectedKey = (SelectionKey)iter.next();
                
                if ((selectedKey.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT){
                    ServerSocketChannel serverChannel = (ServerSocketChannel)selectedKey.channel();
                    SocketChannel socketChannel = serverChannel.accept();
                    socketChannel.configureBlocking(false);
                    
                    socketChannel.register(selector, SelectionKey.OP_READ);                    
                    iter.remove();
                    
                    //System.out.println("buffer: "+new String(buffer.array()));                
                }
                else if ( (selectedKey.readyOps()&SelectionKey.OP_READ) == SelectionKey.OP_READ ){
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    SocketChannel socketChannel = (SocketChannel)selectedKey.channel();
                    while (true){
                        buffer.clear();
                        int i=socketChannel.read(buffer);
                    
                        if (i == -1) break;
                    
                        buffer.flip();
                        socketChannel.write(buffer);
                    }
                }
                
            }
            
        }
       

    }
    
    
}
